package com.Java.train.business.service.daily.Impl;

import cn.hutool.core.util.EnumUtil;
import com.Java.train.business.entity.TrainStation;
import com.Java.train.business.enums.SeatTypeEnum;
import com.Java.train.business.enums.TrainTypeEnum;
import com.Java.train.business.req.daily.DailyTrainTicketQueryReq;
import com.Java.train.business.service.TrainStationService;
import com.Java.train.business.service.daily.DailyTrainCarriageService;
import com.Java.train.business.service.daily.DailyTrainSeatService;
import com.Java.train.common.response.CommonResp;
import com.Java.train.business.entity.DTO.DailyTrainTicketDTO;
import com.Java.train.common.exception.BusniessException;
import com.Java.train.common.exception.BusniessExceptionEnum;
import com.Java.train.common.response.PageResp;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.Java.train.business.entity.DailyTrainTicket;
import com.Java.train.business.mapper.DailyTrainTicketMapper;
import com.Java.train.business.service.daily.DailyTrainTicketService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import com.Java.train.common.utils.SnowFlakeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.date.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Arrays;
import java.util.Collections;
/**
* 余票信息 服务实现类
*
* @author luomoxingchen
* @since 2024-10-01
*/
@Service
public class DailyTrainTicketServiceImpl extends ServiceImpl<DailyTrainTicketMapper, DailyTrainTicket> implements DailyTrainTicketService {

    private static final Logger LOG = LoggerFactory.getLogger(DailyTrainTicketService.class);

    @Autowired
    DailyTrainTicketMapper dailyTrainTicketMapper;
    @Resource
    TrainStationService trainStationService;
    @Resource
    DailyTrainSeatService dailyTrainSeatService;
    @Resource
    DailyTrainCarriageService dailyTrainCarriageService;

    @Override
    public PageResp<DailyTrainTicketDTO> queryList(DailyTrainTicketQueryReq dailyTrainTicketQueryReq){
        // 1.获取当前用户id信息
        //        Long id = LoginMemberContext.getId();
        String trainCode = dailyTrainTicketQueryReq.getTrainCode();
        Date date = dailyTrainTicketQueryReq.getDate();
        String end = dailyTrainTicketQueryReq.getEnd();
        String start = dailyTrainTicketQueryReq.getStart();
        // 2.查询数据库中是否存在当前信息（id）
        LOG.info("查询页码：{}", dailyTrainTicketQueryReq.getPage());
        LOG.info("每页条数：{}", dailyTrainTicketQueryReq.getSize());
        PageHelper.startPage(dailyTrainTicketQueryReq.getPage(),dailyTrainTicketQueryReq.getSize());
        List<DailyTrainTicket> dailyTrainTickets = list();
        LambdaQueryWrapper<DailyTrainTicket> wrapper = new LambdaQueryWrapper<>();
        if(StrUtil.isNotBlank(trainCode)){
            wrapper.eq(DailyTrainTicket::getTrainCode, trainCode);
        }
        if(ObjectUtil.isNotEmpty(date)){
            wrapper.eq(DailyTrainTicket::getDate, date);
        }
        if(StrUtil.isNotBlank(start)){
            wrapper.eq(DailyTrainTicket::getStart, start);
        }
        if(StrUtil.isNotBlank(end)){
            wrapper.eq(DailyTrainTicket::getEnd, end);
        }
        dailyTrainTickets = list(wrapper);
        if(dailyTrainTickets == null || CollUtil.isEmpty(dailyTrainTickets)){
            LOG.info("没有每日车票信息");
//            throw new BusniessException(BusniessExceptionEnum.MEMBER_PASSENGER_NOT_EXITS);
        }

        // 3 分析分页信息
        // 3.1 获取分页总条数和页数
        PageInfo<DailyTrainTicket> pageInfo = new PageInfo<>(dailyTrainTickets);
        LOG.info("总行数：{}", pageInfo.getTotal());
        LOG.info("总页数：{}", pageInfo.getPages());

        // 3.2 转为封装后的返回值并封装到分页返回值中
        List<DailyTrainTicketDTO> list = BeanUtil.copyToList(dailyTrainTickets, DailyTrainTicketDTO.class);
        PageResp<DailyTrainTicketDTO> pageResp = new PageResp<>();
        pageResp.setTotal(pageInfo.getTotal());
        pageResp.setList(list);
        // 4.返回查询到的信息
        return pageResp;
    }

    @Override
    public CommonResp<Object> modify(DailyTrainTicket dailyTrainTicket) {
        Long id = dailyTrainTicket.getId();
        DateTime dateTime = DateTime.now();
        if(ObjectUtil.isNull(id)){
            dailyTrainTicket.setId(SnowFlakeUtil.getSnowFlakeNextId());
            dailyTrainTicket.setCreateTime(dateTime);
            dailyTrainTicket.setUpdateTime(dateTime);
            boolean save = save(dailyTrainTicket);
            return new CommonResp<>(save);
        } else {
            dailyTrainTicket.setUpdateTime(dateTime);
            boolean update = updateById(dailyTrainTicket);
            return new CommonResp<>(update);
        }
    }

    @Override
    public CommonResp<Object> remove(String ids) {
        if(StrUtil.isNotEmpty(ids)){
            String[] array = ids.split(",");
            if(!CollectionUtils.isEmpty(Arrays.asList(array))) {
                return new CommonResp<>(dailyTrainTicketMapper.deleteBatchIds(Arrays.asList(array)));
            }
        }
        return new CommonResp<>(Collections.EMPTY_LIST);
    }

    @Override
    public void genDaily(Date date, String trainCode, String trainType) {
        // 删除之前生成的所有车票数据
        LambdaQueryWrapper<DailyTrainTicket> wrapper = new LambdaQueryWrapper<>();
        remove(wrapper.eq(DailyTrainTicket::getDate, date).eq(DailyTrainTicket::getTrainCode, trainCode));

        // 获取所有车站，然后两两组合全排列生成车票
        LambdaQueryWrapper<TrainStation> trainStationWrapper = new LambdaQueryWrapper<>();
        List<TrainStation> trainStations = trainStationService.list(trainStationWrapper.eq(TrainStation::getTrainCode, trainCode).orderBy(true, true, TrainStation::getIdx));

        if(CollUtil.isEmpty(trainStations)){
            LOG.info("该火车车站信息为空");
            return ;
        }

        int n = trainStations.size();
        Date dateTime = DateTime.now();
        for(int i = 0; i < n - 1; i++){
            TrainStation trainStationStart = trainStations.get(i);
            // 统计站点总路程
            BigDecimal sumKm = BigDecimal.ZERO;
            for(int j = i + 1; j < n; j++){
                TrainStation trainStationEnd = trainStations.get(j);

                // 生成车票信息
                DailyTrainTicket dailyTrainTicket = new DailyTrainTicket();
                dailyTrainTicket.setId(SnowFlakeUtil.getSnowFlakeNextId());
                dailyTrainTicket.setDate(date);
                dailyTrainTicket.setTrainCode(trainCode);
                dailyTrainTicket.setStart(trainStationStart.getName());
                dailyTrainTicket.setStartPinyin(trainStationStart.getNamePinyin());
                dailyTrainTicket.setStartTime(trainStationStart.getOutTime());
                dailyTrainTicket.setStartIndex(trainStationStart.getIdx());
                dailyTrainTicket.setEnd(trainStationEnd.getName());
                dailyTrainTicket.setEndPinyin(trainStationEnd.getNamePinyin());
                dailyTrainTicket.setEndTime(trainStationEnd.getOutTime());
                dailyTrainTicket.setEndIndex(trainStationEnd.getIdx());
                // 通过count统计dailySeat的座次树
                long start = System.currentTimeMillis();
//                LambdaQueryWrapper<DailyTrainSeat> seatWrapper = new LambdaQueryWrapper<>(); // 将此处有数据的edz放到ydz查询前就能查到数据，因此wrapper是专用查询，只能查询一次
//                long edz = dailyTrainSeatService.count(seatWrapper.eq(DailyTrainSeat::getDate,date).eq(DailyTrainSeat::getTrainCode, trainCode).eq(DailyTrainSeat::getSeatType, SeatTypeEnum.EDZ.getCode()));
//                long ydz = dailyTrainSeatService.count(seatWrapper.eq(DailyTrainSeat::getDate,date).eq(DailyTrainSeat::getTrainCode, trainCode).eq(DailyTrainSeat::getSeatType, SeatTypeEnum.YDZ.getCode()));
////                long edz = dailyTrainSeatService.count(seatWrapper.eq(DailyTrainSeat::getDate,date).eq(DailyTrainSeat::getTrainCode, trainCode).eq(DailyTrainSeat::getSeatType, SeatTypeEnum.EDZ.getCode()));
//                long rw = dailyTrainSeatService.count(seatWrapper.eq(DailyTrainSeat::getDate,date).eq(DailyTrainSeat::getTrainCode, trainCode).eq(DailyTrainSeat::getSeatType, SeatTypeEnum.RW.getCode()));
//                long yw = dailyTrainSeatService.count(seatWrapper.eq(DailyTrainSeat::getDate,date).eq(DailyTrainSeat::getTrainCode, trainCode).eq(DailyTrainSeat::getSeatType, SeatTypeEnum.YW.getCode()));
                int ydz = dailyTrainSeatService.countTypeSeat(date, trainCode, SeatTypeEnum.YDZ.getCode());
                int edz = dailyTrainSeatService.countTypeSeat(date, trainCode, SeatTypeEnum.EDZ.getCode());
                int rw = dailyTrainSeatService.countTypeSeat(date, trainCode, SeatTypeEnum.RW.getCode());
                int yw = dailyTrainSeatService.countTypeSeat(date, trainCode, SeatTypeEnum.YW.getCode());

                long end = System.currentTimeMillis();
                LOG.info("所耗时为：{}", end - start);
                LOG.info("一等座为：{}， 二等座为：{}， 软卧为：{}，硬卧为：{}", ydz, edz, rw, yw);
                // 计算票价（票价 = 两站路程 * 车类型每公里单件 * 列车属性）
                sumKm = sumKm.add(trainStationEnd.getKm());
                // 得到trainType中的倍率
                BigDecimal priceRate = EnumUtil.getFieldBy(TrainTypeEnum::getPriceRate, TrainTypeEnum::getCode, trainType);
                BigDecimal ydzMon = sumKm.multiply(SeatTypeEnum.YDZ.getPrice()).multiply(priceRate).setScale(2, RoundingMode.HALF_UP);
                BigDecimal edzMon = sumKm.multiply(SeatTypeEnum.EDZ.getPrice()).multiply(priceRate).setScale(2, RoundingMode.HALF_UP);
                BigDecimal rwMon = sumKm.multiply(SeatTypeEnum.RW.getPrice()).multiply(priceRate).setScale(2, RoundingMode.HALF_UP);
                BigDecimal ywMon = sumKm.multiply(SeatTypeEnum.YW.getPrice()).multiply(priceRate).setScale(2, RoundingMode.HALF_UP);

                dailyTrainTicket.setYdz((int) ydz);
                dailyTrainTicket.setYdzPrice(ydzMon);
                dailyTrainTicket.setEdz((int) edz);
                dailyTrainTicket.setEdzPrice(edzMon);
                dailyTrainTicket.setRw((int) rw);
                dailyTrainTicket.setRwPrice(rwMon);
                dailyTrainTicket.setYw((int) yw);
                dailyTrainTicket.setYwPrice(ywMon);
                dailyTrainTicket.setCreateTime(dateTime);
                dailyTrainTicket.setUpdateTime(dateTime);
                save(dailyTrainTicket);
            }
        }
    }

}


